package com.rede.didiok.pay.service.impl.PayServiceImpl;


import java.math.BigDecimal;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.domainEvent.EventAction;
import com.rede.didiok.common.dto.pay.PayOrderDto;
import com.rede.didiok.common.enums.OrderStatusEnum;
import com.rede.didiok.common.enums.PayMethodEnum;
import com.rede.didiok.common.exception.exceptionType.InsertException;
import com.rede.didiok.common.holder.RequestHolder;
import com.rede.didiok.common.utils.ResultUtil;
import com.rede.didiok.common.utils.StringUtils;
import com.rede.didiok.common.utils.business.DomainEventUtil;
import com.rede.didiok.pay.annotation.PayMethod;
import com.rede.didiok.pay.entity.PayOrderEntity;
import com.rede.didiok.pay.model.bean.YunGouOSWxPayBean;
import com.rede.didiok.pay.service.PayOrderService;
import com.rede.didiok.pay.service.PayService;
import com.yungouos.pay.util.PaySignUtil;
import com.yungouos.pay.wxpay.WxPay;

/**
 * 第三方微信支付服务
 *
 * @author 陌溪
 */
@Service
@PayMethod({PayMethodEnum.YUN_GOU_OS_WECHAT_PAY})
@Slf4j
public class YunGouOSWechatPayService implements PayService {

    @Resource
    private PayOrderService payOrderService;

    @Resource
    private YunGouOSWxPayBean yunGouOSWxPayBean;

    @Resource
    private DomainEventUtil domainEventUtil;

    /**
     * 普通公钥模式
     */
    private final static String NOTIFY_URL = "/trade/yunGouOSWxPay/callback";

    @Override
    public String pay(String payOrderUid) {
        // 获取支付订单
        PayOrderEntity payOrder = payOrderService.getById(payOrderUid);
        if (payOrder == null) {
            log.error("支付订单不存在: payOrderUid: {}", payOrderUid);
            throw new InsertException("支付订单不存在");
        }
        BigDecimal price = payOrder.getTotalPrice();
        String totalAmount = price.stripTrailingZeros().toPlainString();

        // 参数文档：https://open.pay.yungouos.com/#/api/api/pay/wxpay/nativePay
        String result = WxPay.nativePay(payOrder.getUid(),
                totalAmount, yunGouOSWxPayBean.getMchId(), payOrder.getTitle(),
                "1",  // 返回类型（1、返回微信原生的支付连接需要自行生成二维码；2、直接返回付款二维码地址，页面上展示即可。不填默认1 ）
                null, payOrder.getUid(), yunGouOSWxPayBean.getDomain().concat(NOTIFY_URL), null, null, "0", null, null, yunGouOSWxPayBean.getKey());

        // 订单创建成功
        PayOrderDto dto = new PayOrderDto();
        BeanUtils.copyProperties(payOrder, dto);
        domainEventUtil.publishEvent(EventAction.ORDER_CREATE_SUCCESS, dto);

        return ResultUtil.successWithData(result);
    }

    @Override
    public String callback() {
        HttpServletRequest request = RequestHolder.getRequest();
        log.info("接收到第三方支付回调通知");
        try {
            boolean sign = PaySignUtil.checkNotifySign(request, yunGouOSWxPayBean.getKey());
            if (!sign) {
                log.error("签证校验未通过");
                return "FAIL";
            }
            String orderUid = request.getParameter("outTradeNo");
            // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
            // 注意此处签名方式需与统一下单的签名类型一致
            if (StringUtils.isNotEmpty(orderUid)) {
                // 更新订单信息
                PayOrderEntity payOrder = payOrderService.getById(orderUid);
                if (payOrder == null) {
                    log.error("获取订单失败, orderUid: {}", orderUid);
                    // 发送通知等
                    return "FAIL";
                }
                if (OrderStatusEnum.Finish.equals(payOrder.getOrderStatus())) {
                    log.info("支付已完成, orderUid: {}", orderUid);
                    return "SUCCESS";
                }
                payOrder.setOrderStatus(OrderStatusEnum.Finish);
                payOrder.updateById();

                // 执行分账逻辑


                // 订单支付成功
                domainEventUtil.publishEvent(EventAction.ORDER_PAY_SUCCESS, payOrder);
                return "SUCCESS";
            }
        } catch (Exception e) {
            log.error("[callback] 第三方微信支付回调异常");
            e.printStackTrace();
        }
        return "FAIL";
    }

    @Override
    public String closePayOrder(PayOrderEntity payOrder) {
        String result = WxPay.closeOrder(payOrder.getUid(), yunGouOSWxPayBean.getMchId(), yunGouOSWxPayBean.getKey());
        log.info("[closePayOrder] result: {}", result);
        return ResultUtil.successWithMessage(MessageConf.UPDATE_SUCCESS);
    }
}
